
`include "common_header.verilog"


//  *************************************************************************
//   File : top_xgxs_rx.v
//  *************************************************************************
//   This program is controlled by a written license agreement.
//   Unauthorized Reproduction or Use is Expressly Prohibited. 
//  Copyright (c) 2005 Morethanip GmbH
//  info@morethanip.com
//  *************************************************************************
//  Version: $Id: top_xgxs_rx.v,v 1.9 2008/01/16 21:01:24 mr Exp $ 
//  Author : Muhammad Anisur Rahman
//  *************************************************************************
//   Description:
// 
//   10 Gigabit Ethernet XGXS PCS Top-Level
// 
//  *************************************************************************

module top_xgxs_rx (

   reset_sd0_rx_clk,
   reset_sd1_rx_clk,
   reset_sd2_rx_clk,
   reset_sd3_rx_clk,
   reset_xgmii_rxclk,
   xgmii_rxclk,
  `ifdef ENA_RX_RATE_MATCHING   
  `ifdef USE_CLK_ENA
   xgmii_rxclk_ena,
  `endif
   jumbo_en,
  `endif
   xgmii_rxd,
   xgmii_rxc,
   sd0_rx,
   sd0_rx_clk,
  `ifdef USE_CLK_ENA
   sd0_rx_clk_ena,
  `endif
   sd1_rx,
   sd1_rx_clk,
  `ifdef USE_CLK_ENA
   sd1_rx_clk_ena,
  `endif
   sd2_rx,
   sd2_rx_clk,
  `ifdef USE_CLK_ENA
   sd2_rx_clk_ena,
  `endif
   sd3_rx,
   sd3_rx_clk,
  `ifdef USE_CLK_ENA
   sd3_rx_clk_ena,
  `endif
   sd_signal0,
   sd_signal1,
   sd_signal2,
   sd_signal3,
  `ifdef MTIPXGXS_BUFRESET
   buf_reset,
  `endif   
   align_done,
   char_err,
   disp_err,
   sync,
   cg_align,
   pat,
   match_fault);

`include "mtip_xgxs_package.verilog"

input   reset_sd0_rx_clk;       //  Asynchronous Reset - sd0_rx_clk Domain
input   reset_sd1_rx_clk;       //  Asynchronous Reset - sd1_rx_clk Domain
input   reset_sd2_rx_clk;       //  Asynchronous Reset - sd2_rx_clk Domain
input   reset_sd3_rx_clk;       //  Asynchronous Reset - sd3_rx_clk Domain
input   reset_xgmii_rxclk;      //  Asynchronous Reset - xgmii_rxclk Domain
input   xgmii_rxclk;            //  156.25MHz Receive Clock
output  [63:0] xgmii_rxd;       //  Receive Data
output  [7:0] xgmii_rxc;        //  Receive Control        
input   [19:0] sd0_rx;          //  SERDES Lane 0
input   sd0_rx_clk;             //  SERDES Lane 0 Clock
input   [19:0] sd1_rx;          //  SERDES Lane 1
input   sd1_rx_clk;             //  SERDES Lane 1 Clock
input   [19:0] sd2_rx;          //  SERDES Lane 2
input   sd2_rx_clk;             //  SERDES Lane 2 Clock
input   [19:0] sd3_rx;          //  SERDES Lane 3
input   sd3_rx_clk;             //  SERDES Lane 3 Clock
input   sd_signal0;             //  SERDES Lane 0 Status        
input   sd_signal1;             //  SERDES Lane 1 Status        
input   sd_signal2;             //  SERDES Lane 2 Status        
input   sd_signal3;             //  SERDES Lane 3 Status
`ifdef MTIPXGXS_BUFRESET
   output [3:0] buf_reset;      //  Rset buffers when deskew error occured
`endif
output  align_done;             //  Lane Alignment Done
output  [3:0] char_err;         //  Character Error Indication
output  [3:0] disp_err;         //  Disparity Error Indication
output  [3:0] sync;             //  Channel Synchronization Indication
output  [3:0] pat;              //  Comma Detected Indication
output  match_fault;            //  Rate Matching Error Indication
output  [3:0] cg_align;         //  Code Group Alignment Indication

`ifdef USE_CLK_ENA
   input sd0_rx_clk_ena;        // Enable sd0_rx_clk
   input sd1_rx_clk_ena;        // Enable sd1_rx_clk
   input sd2_rx_clk_ena;        // Enable sd2_rx_clk
   input sd3_rx_clk_ena;        // Enable sd3_rx_clk
`endif 

`ifdef ENA_RX_RATE_MATCHING
`ifdef USE_CLK_ENA
input   xgmii_rxclk_ena;       // Enable xgmii_rxclk
`endif
input   jumbo_en;               //  increase thresholds(=latency) to support jumbo frames
`endif

wire    [63:0] xgmii_rxd; 
wire    [7:0] xgmii_rxc; 
`ifdef MTIPXGXS_BUFRESET
wire    [3:0] buf_reset;      //  Reset buffers when deskew error occured
`endif
wire    align_done; 
wire    [3:0] char_err; 
wire    [3:0] disp_err; 
wire    [3:0] sync; 
wire    [3:0] pat; 
wire    match_fault;
wire    [3:0] cg_align;

// 8b/10b Decoder
// -------------- 

wire    [15:0] dec_dout0;       //  parallel output data        
wire    [1:0] dec_kout0;        //  special caracter detected        
wire    [1:0] dec_error0;       //  flag asserted when the data in detected faulty                
wire    [1:0] disp_error0;      //  flag asserted when a disparity error is detected                
wire    [15:0] dec_dout1;       //  parallel output data        
wire    [1:0] dec_kout1;        //  special caracter detected        
wire    [1:0] dec_error1;       //  flag asserted when the data in detected faulty                
wire    [1:0] disp_error1;      //  flag asserted when a disparity error is detected                
wire    [15:0] dec_dout2;       //  parallel output data        
wire    [1:0] dec_kout2;        //  special caracter detected        
wire    [1:0] dec_error2;       //  flag asserted when the data in detected faulty                
wire    [1:0] disp_error2;      //  flag asserted when a disparity error is detected                
wire    [15:0] dec_dout3;       //  parallel output data        
wire    [1:0] dec_kout3;        //  special caracter detected        
wire    [1:0] dec_error3;       //  flag asserted when the data in detected faulty                
wire    [1:0] disp_error3;      //  flag asserted when a disparity error is detected                

//  Lane Synchronization
//  --------------------   

wire    [3:0] sync_acqurd;      //  Synchronization Acquired
wire    [3:0] enable_cgalign;   //  Enable code group alignment

//  Aligned Lanes
//  -------------

wire    align_done_int;         //  Lane Aligned Status   
wire    [15:0] dout0;           //  parallel output data        
wire    [1:0] kout0;            //  special caracter detected        
wire    [15:0] dout1;           //  parallel output data        
wire    [1:0] kout1;            //  special caracter detected        
wire    [15:0] dout2;           //  parallel output data        
wire    [1:0] kout2;            //  special caracter detected        
wire    [15:0] dout3;           //  parallel output data        
wire    [1:0] kout3;            //  special caracter detected        

// Check End function
// ------------------

wire    ln_align_ckd;           //  Lane Alignment Done checked       
wire    [1:0] k_ckd0;           //  Special Character Indication checked
wire    [15:0] d_ckd0;          //  Decoded Data checked     
wire    [1:0] k_ckd1;           //  Special Character Indication checked
wire    [15:0] d_ckd1;          //  Decoded Data checked
wire    [1:0] k_ckd2;           //  Special Character Indication checked
wire    [15:0] d_ckd2;          //  Decoded Data checked
wire    [1:0] k_ckd3;           //  Special Character Indication checked
wire    [15:0] d_ckd3;          //  Decoded Data checked

//  XGMII Interface
//  ---------------

`ifdef MTIPXGXS_DPREGS

reg     [63:0] xgmii_rxd_int;   //  Receive Data
reg     [7:0] xgmii_rxc_int;    //  Receive Control 

`else

wire    [63:0] xgmii_rxd_int;   //  Receive Data
wire    [7:0] xgmii_rxc_int;    //  Receive Control 

`endif

wire    gnd; 
wire    vcc; 

assign gnd = 1'b 0; 
assign vcc = 1'b 1; 

top_dec10b8b U_DEC0 (

          .rst_align(gnd),
          .din(sd0_rx),
          .ce(vcc),
          .dout(dec_dout0),
          .kout(dec_kout0),
          .char_err(dec_error0),
          .disp_err(disp_error0),
          .sync(cg_align[0]),
          .comma(pat[0]),
          .clk(sd0_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd0_rx_clk_ena),
          `endif
          .enable_cgalign(enable_cgalign[0]),
          .rst(reset_sd0_rx_clk));

top_dec10b8b U_DEC1 (

          .rst_align(gnd),
          .din(sd1_rx),
          .ce(vcc),
          .dout(dec_dout1),
          .kout(dec_kout1),
          .char_err(dec_error1),
          .disp_err(disp_error1),
          .sync(cg_align[1]),
          .comma(pat[1]),
          .clk(sd1_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd1_rx_clk_ena),
          `endif
          .enable_cgalign(enable_cgalign[1]),
          .rst(reset_sd1_rx_clk));

top_dec10b8b U_DEC2 (

          .rst_align(gnd),
          .din(sd2_rx),
          .ce(vcc),
          .dout(dec_dout2),
          .kout(dec_kout2),
          .char_err(dec_error2),
          .disp_err(disp_error2),
          .sync(cg_align[2]),
          .comma(pat[2]),
          .clk(sd2_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd2_rx_clk_ena),
          `endif          
          .enable_cgalign(enable_cgalign[2]),
          .rst(reset_sd2_rx_clk));

top_dec10b8b U_DEC3 (

          .rst_align(gnd),
          .din(sd3_rx),
          .ce(vcc),
          .dout(dec_dout3),
          .kout(dec_kout3),
          .char_err(dec_error3),
          .disp_err(disp_error3),
          .sync(cg_align[3]),
          .comma(pat[3]),
          .clk(sd3_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd3_rx_clk_ena),
          `endif          
          .enable_cgalign(enable_cgalign[3]),
          .rst(reset_sd3_rx_clk));

rx_xgxs_sync U_SYNC0 (

          .reset(reset_sd0_rx_clk),
          .clk(sd0_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd0_rx_clk_ena),
          `endif           
          .signal_detect(sd_signal0),
          .kchar(dec_kout0),
          .data(dec_dout0),
          .disp_err(disp_error0),
          .dec_error(dec_error0),
          .enable_cgalign(enable_cgalign[0]),
          .sync_acqurd(sync_acqurd[0]));

rx_xgxs_sync U_SYNC1 (

          .reset(reset_sd1_rx_clk),
          .clk(sd1_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd1_rx_clk_ena),
          `endif          
          .signal_detect(sd_signal1),
          .kchar(dec_kout1),
          .data(dec_dout1),
          .disp_err(disp_error1),
          .dec_error(dec_error1),
          .enable_cgalign(enable_cgalign[1]),
          .sync_acqurd(sync_acqurd[1]));

rx_xgxs_sync U_SYNC2 (

          .reset(reset_sd2_rx_clk),
          .clk(sd2_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd2_rx_clk_ena),
          `endif
          .signal_detect(sd_signal2),
          .kchar(dec_kout2),
          .data(dec_dout2),
          .disp_err(disp_error2),
          .dec_error(dec_error2),
          .enable_cgalign(enable_cgalign[2]),
          .sync_acqurd(sync_acqurd[2]));

rx_xgxs_sync U_SYNC3 (

          .reset(reset_sd3_rx_clk),
          .clk(sd3_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd3_rx_clk_ena),
          `endif
          .signal_detect(sd_signal3),
          .kchar(dec_kout3),
          .data(dec_dout3),
          .disp_err(disp_error3),
          .dec_error(dec_error3),
          .enable_cgalign(enable_cgalign[3]),
          .sync_acqurd(sync_acqurd[3]));

rx_lane_dskew U_DSK (

          .reset_sd0_rx_clk(reset_sd0_rx_clk),
          .reset_sd1_rx_clk(reset_sd1_rx_clk),
          .reset_sd2_rx_clk(reset_sd2_rx_clk),
          .reset_sd3_rx_clk(reset_sd3_rx_clk),
          .rx_sync(sync_acqurd),
          .sd0_rx_clk(sd0_rx_clk),
          `ifdef USE_CLK_ENA
           .sd0_rx_clk_ena(sd0_rx_clk_ena),
          `endif           
          .dec_kchar0(dec_kout0),
          .dec_data0(dec_dout0),
          .sd1_rx_clk(sd1_rx_clk),
          `ifdef USE_CLK_ENA
           .sd1_rx_clk_ena(sd1_rx_clk_ena),
          `endif           
          .dec_kchar1(dec_kout1),
          .dec_data1(dec_dout1),
          .sd2_rx_clk(sd2_rx_clk),
          `ifdef USE_CLK_ENA
           .sd2_rx_clk_ena(sd2_rx_clk_ena),
          `endif
          .dec_kchar2(dec_kout2),
          .dec_data2(dec_dout2),
          .sd3_rx_clk(sd3_rx_clk),
          `ifdef USE_CLK_ENA
           .sd3_rx_clk_ena(sd3_rx_clk_ena),
          `endif
          .dec_kchar3(dec_kout3),
          .dec_data3(dec_dout3),
          .kchar0(kout0),
          .data0(dout0),
          .kchar1(kout1),
          .data1(dout1),
          .kchar2(kout2),
          .data2(dout2),
          .kchar3(kout3),
          .data3(dout3),
          `ifdef MTIPXGXS_BUFRESET
           .buf_reset(buf_reset),
          `endif
          .align_done(align_done_int));

check_end U_CHECK_END (

          .reset(reset_sd0_rx_clk),
          .clk(sd0_rx_clk),
          `ifdef USE_CLK_ENA
           .clk_ena(sd0_rx_clk_ena),
          `endif           
          .ln_align(align_done_int),
          .kchar0(kout0),
          .data0(dout0),
          .kchar1(kout1),
          .data1(dout1),
          .kchar2(kout2),
          .data2(dout2),
          .kchar3(kout3),
          .data3(dout3),
          .ln_align_ckd(ln_align_ckd),
          .k_ckd0(k_ckd0),
          .d_ckd0(d_ckd0),
          .k_ckd1(k_ckd1),
          .d_ckd1(d_ckd1),
          .k_ckd2(k_ckd2),
          .d_ckd2(d_ckd2),
          .k_ckd3(k_ckd3),
          .d_ckd3(d_ckd3));

`ifdef MTIPXGXS_DPREGS

always @(posedge reset_sd0_rx_clk or posedge sd0_rx_clk)
begin
        if( reset_sd0_rx_clk==1'b 1 ) 
        begin
                xgmii_rxd_int <= 64'h 0;
                xgmii_rxc_int <= 8'h 0;
        end
        else
        begin
                
                `ifdef USE_CLK_ENA
                if(sd0_rx_clk_ena == 1'b 1)
                begin
                `endif          

                xgmii_rxd_int <= ({d_ckd3[15:8], d_ckd2[15:8], d_ckd1[15:8], d_ckd0[15:8], d_ckd3[7:0], d_ckd2[7:0], d_ckd1[7:0], d_ckd0[7:0]});
                xgmii_rxc_int <= ({k_ckd3[1], k_ckd2[1], k_ckd1[1], k_ckd0[1], k_ckd3[0], k_ckd2[0], k_ckd1[0], k_ckd0[0]});

                `ifdef USE_CLK_ENA
                end
                `endif

        end

end

`else

assign xgmii_rxd_int = ({d_ckd3[15:8], d_ckd2[15:8], d_ckd1[15:8], d_ckd0[15:8], d_ckd3[7:0], d_ckd2[7:0], d_ckd1[7:0], d_ckd0[7:0]});
assign xgmii_rxc_int = ({k_ckd3[1], k_ckd2[1], k_ckd1[1], k_ckd0[1], k_ckd3[0], k_ckd2[0], k_ckd1[0], k_ckd0[0]});

`endif
          
`ifdef ENA_RX_RATE_MATCHING

   fiform U_RM (

          .reset_ln_clk(reset_sd0_rx_clk),
          .reset_xgmii_clk(reset_xgmii_rxclk),
          .jumbo_en(jumbo_en),
          .ln_clk(sd0_rx_clk),
          `ifdef USE_CLK_ENA
          .ln_clk_ena(sd0_rx_clk_ena),
          `endif
          .ln_rxd(xgmii_rxd_int),
          .ln_rxc(xgmii_rxc_int),
          .fifo_fault(match_fault),
          .xgmii_clk(xgmii_rxclk),
          `ifdef USE_CLK_ENA
          .xgmii_clk_ena(xgmii_rxclk_ena),
          `endif
          .xgmii_rxd(xgmii_rxd),
          .xgmii_rxc(xgmii_rxc));
          
`else
        
        assign match_fault = 1'b0 ;

        assign xgmii_rxd = xgmii_rxd_int ;
        assign xgmii_rxc = xgmii_rxc_int ;
        
`endif          

assign align_done  = align_done_int; 
assign sync        = sync_acqurd; 
assign char_err[0] = dec_error0[0]  | dec_error0[1]; 
assign char_err[1] = dec_error1[0]  | dec_error1[1]; 
assign char_err[2] = dec_error2[0]  | dec_error2[1]; 
assign char_err[3] = dec_error3[0]  | dec_error3[1]; 
assign disp_err[0] = disp_error0[0] | disp_error0[1]; 
assign disp_err[1] = disp_error1[0] | disp_error1[1]; 
assign disp_err[2] = disp_error2[0] | disp_error2[1]; 
assign disp_err[3] = disp_error3[0] | disp_error3[1];

endmodule // module top_xgxs_rx

